package com.example.emqx.redis;

import com.example.emqx.entity.RedisUser;
import com.example.emqx.service.RedisUserService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class AnnotateRedisService {
    @Autowired
    private RedisUserService redisUserService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private ObjectMapper objectMapper;

    //    @Cacheable
//    用于标注一个方法的返回结果可以被缓存。
//    当方法被调用时，Spring 首先会检查 Redis 缓存中是否存在该方法的返回值。如果存在，则直接从缓存中返回，否则执行该方法并将结果缓存。
    @Cacheable(value = "users", key = "'redisUser_'+#userId")
    public RedisUser cacheRedisUser(Long userId) {
        return redisUserService.getById(userId);
    }

    //    @CachePut
//    用于更新缓存数据。即使缓存中存在对应的值，方法依然会被执行，且返回结果会更新到缓存中。
    @CachePut(value = "users", key = "'redisUser_'+#user.id")
    public RedisUser cachePutUser(RedisUser user) {
        boolean success = redisUserService.saveOrUpdate(user);
        if (success) {
            return user;  // 成功时返回用户对象并缓存
        } else {
            return null;  // 如果保存失败，返回 null
        }
    }

    //    @CacheEvict
//    用于从缓存中移除某个或多个键对应的值，通常用于删除或更新操作。
    @CacheEvict(value = "users", key = "'redisUser_'+#id")
    public void testCacheEvict(Long id) {
        log.info("testCacheEvict---{}", id);
        // 删除数据库
        boolean success = redisUserService.removeById(id);
        log.info("success---{}", success);

    }

    //        @Caching
//    用于组合多个缓存操作，比如 @Cacheable、@CachePut 和 @CacheEvict。
    @Caching(evict = {
            @CacheEvict(value = "users", key = "'redisUser_'+#id"),
            @CacheEvict(value = "username", key = "'username_'+#username")
    })
    public void testCaching(String username, Long id) {
        log.info("testCaching---username:{},id:{}", username, id);
        // 查询数据库或其他逻辑
        redisUserService.removeById(id);
    }
    // 设置过期时间
    public RedisUser saveUserWithExpiration(Long userId, long expirationTimeInSeconds) throws JsonProcessingException {
        // 存入 Redis
        String key = "redisUser_" + userId;
        if (Boolean.TRUE.equals(stringRedisTemplate.hasKey(key))) {
            String json = stringRedisTemplate.opsForValue().get(key);
            return objectMapper.readValue(json, RedisUser.class);
        }
        RedisUser redisUser = redisUserService.getById(userId);
        if (redisUser != null) {
            redisUser.setExpiration(expirationTimeInSeconds);
            String json = objectMapper.writeValueAsString(redisUser);
            stringRedisTemplate.opsForValue().set(key, json, expirationTimeInSeconds, TimeUnit.SECONDS);
        }
        return redisUser;
    }
}
